﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using AMStudio.Common;
using System.Text.RegularExpressions;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using AMStudio.DelegateDispather;
using System.IO.Ports;
using System.Threading;
using System.Data;
//using CustomerSnMaker;

namespace AMStudio.Driver
{
    public class TraceDriver : IAutomationDriver
    {
        protected ExceptionManager ExManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();

        private TraceRealConfig myConfig = null;
        private DelegateDispather.IEventClient eventClient;
        public DelegateDispather.IEventClient EventClient
        {
            get { return eventClient; }
            set { eventClient = value; }
        }
        private TTACTracDriver hardwaredriver;
        private bool alreadyinitialized = false;
        private IExecuteReader result = new ExecuteReader(false);
        private int taskid=-1;

        private String hardwareName = "TRACE";
        public String HardwareName
        {
            get { return hardwareName; }
            set { hardwareName = value; }
        }
        private String hardwareEvent = "TRACE_RET";
        public String HardwareEvent
        {
            get { return hardwareEvent; }
            set { hardwareEvent = value; }
        }

        public delegate object ExecuteReaderCaller(string serialNumber, string housingId, string scannedMaterialNr, string partNr);  //定义个代理 
        ExecuteReaderCaller bomCheckCaller;
        IAsyncResult bomCheckResult;

        public delegate object UploadAndDispatch(string serialNumber, string customerSN, int failStation, bool isDispatch);
        UploadAndDispatch uploadAndDispatchCaller;
        IAsyncResult uploadAndDispatchResult;

        public void Initialize(IEventManager eventManager, TraceRealConfig config)
        {
            myConfig = config;
            //hardwaredriver = new TTACTracDriver(config.PathName,config.StationNo,config.ConsoleEnable);
            hardwaredriver = new TTACTracDriver();
            hardwaredriver.OnConnected += new TracConnectedHandler(hardwaredriver_OnConnected);
            hardwaredriver.OnConnectClosed += new TracConnectClosedHandler(hardwaredriver_OnConnectClosed);
            eventClient = new EventClient(eventManager);
            this.hardwareEvent = config.HardwareEvent;
            this.hardwareName = config.HardwareName;
        }
        public virtual int ExecuteNonQuery(string command, params object[] parameters)
        {
            return -1;
        }
        public virtual IExecuteReader ExecuteReader(string command, params object[] parameters)
        {
            _Signal_Command_Finished.Reset();
            _Received_Data = null;
            result.Success = false;
            try
            {
                switch (command)
                {
                    case "INIT":
                        #region Command "INIT"
                        {
                            if (!alreadyinitialized)
                            {
                                taskid = -1;
                                this.Initialize((IEventManager)parameters[0], TraceRealConfig.Default);
                                if (!hardwaredriver.Initialize(out taskid))
                                {
                                    Logger.Write("System Error! (Can not connect the laser controller!)");
                                    hardwaredriver.Close();
                                }
                                else
                                {                                    
                                    result.Success = true;
                                    result.Result = taskid;
                                    alreadyinitialized = true;
                                }
                            }
                        }
                        #endregion
                        break;
                    case "EXIT":
                        #region Command "DISCONNECT"
                        result.Success = true;
                        if (alreadyinitialized)
                        {
                            taskid = -1;
                            hardwaredriver.Close();
                            alreadyinitialized = false;
                        }
                        #endregion
                        break;
                    case "CONNECT_STATUS":
                        #region Command "CONNECT_STATUS"
                        {
                            if (alreadyinitialized)
                            {
                                result.Result = true;
                                result.Success = true;
                            }
                            else
                            {
                                result.Result = false;
                                result.Success = true;
                            }

                        }
                        #endregion
                        break;
                    case "DEACTIVATE_WORKORDER":
                        #region Command "DEACTIVATE_WORKORDER"
                        {
                            if (alreadyinitialized)
                            {
                                this.hardwaredriver.ClearMaterialTable();

                                result.Result = true;
                                result.Success = true;
                            }
                        }
                        #endregion
                        break;
                    #region RSU
                    case "SETPRODUCT":
                        #region Command "SETPRODUCT"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;

                                string pr_id = (string)parameters[0];
                                int res = (int)parameters[1];
                                string cust_sn = (string)parameters[2];
                                int ret = this.hardwaredriver.SetProductState(pr_id, cust_sn, res);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = ret;//(object)(new object[] { ret, szInfo });
                            }
                        }
                        #endregion
                        break;
                    case "PACKING":
                        #region Command "PACKING"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                               
                                string cust_sn = (string)parameters[0];
                                string boxNo = (string)parameters[1];
                                int packStatus=0;
                                int ret = this.hardwaredriver.Packing(cust_sn,boxNo,out packStatus);

                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, packStatus });
                            }
                        }
                        #endregion
                        break;
                    case "GETPRODUCT":
                        #region Command "GETPRODUCT"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;

                                string pr_id = (string)parameters[0];
                                int ret = this.hardwaredriver.GetIdStatesReinjection(pr_id);

                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = ret;
                            }
                        }
                        #endregion
                        break;
                    case "CUSTOMERSN_MAKE":
                        #region CustomerSNMarker
                        if (alreadyinitialized)
                        {
                            int id=taskid;
                            string productName = parameters[0].ToString();
                            string snInCreateCust = parameters[1].ToString();
                            string contextFormat = parameters[2].ToString();
                            string format = parameters[3].ToString();
                            int length = (int)parameters[4];
                            string dataFormat = parameters[5].ToString();
                            string real_custsntext = string.Empty;
                            string real_dddy = string.Empty;
                            string customerid = string.Empty;
                            customerid=hardwaredriver.CreateCustomerSN(id, productName, snInCreateCust, contextFormat, format,
                                length,dataFormat,ref real_custsntext, ref real_dddy);
                            //cust_dll.CreateCustomerSN(id, productName, snInCreateCust, true, 
                            //    ref real_custsntext, ref real_dddy);
                            result.Result = new string[] { customerid,real_custsntext, real_dddy };
                            result.Success = true;
                        }
                        #endregion
                        break;
                    case "CHECK_MATERIAL":
                        #region Command "CHECK_MATERIAL"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string scannedMaterialNr = parameters[0].ToString();
                                bool ret = this.hardwaredriver.CheckMaterial(scannedMaterialNr);
                                result.Success = ret;
                                result.Result = ret;
                            }
                        }
                        #endregion
                        break;
                    case "BOM_CHECK_STATION_SETUP":
                        #region Command "BOM_CHECK_STATION_SETUP"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string workOrder;
                                string compName;
                                string partNr;
                                int ret = this.hardwaredriver.BomCheckStationSetup(out workOrder, out compName, out partNr);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, workOrder, compName, partNr });
                            }
                        }
                        #endregion
                        break;
                    case "ACTIVATE_MATERIAL_BOX":
                        #region Command "ACTIVATE_MATERIAL_BOX"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string scannedMaterialNr = parameters[0].ToString();
                                int ret = this.hardwaredriver.ActivateMaterialBox(scannedMaterialNr);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = ret;
                            }
                        }
                        #endregion
                        break;
                    case "BOM_CHECK":
                        #region Command "BOM_CHECK"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string serialNumber = parameters[0].ToString();
                                string housingId = parameters[1].ToString();
                                string scannedMaterialNr = parameters[2].ToString();
                                string partNr = parameters[3].ToString();
                                double quantity;
                                double totalQuantity;
                                int ret = this.hardwaredriver.DoBomCheck(serialNumber, housingId, scannedMaterialNr, partNr, out quantity, out totalQuantity);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }

                                //result.Success = true;
                                int intQuantity = Convert.ToInt32(quantity);
                                int intTotalQuantity = Convert.ToInt32(totalQuantity);
                                result.Result = (object)(new object[] { ret, intQuantity, intTotalQuantity });
                            }
                        }
                        #endregion
                        break;
                    case "BOM_CHECK2":
                        #region Command "BOM_CHECK2"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string serialNumber = parameters[0].ToString();
                                string housingId = parameters[1].ToString();
                                string scannedMaterialNr = parameters[2].ToString();
                                string partNr = parameters[3].ToString();
                                bomCheckCaller = new ExecuteReaderCaller(this.hardwaredriver.DoBomCheck2);
                                bomCheckResult = bomCheckCaller.BeginInvoke(serialNumber, housingId, scannedMaterialNr, partNr, null, null);
                            }
                        }
                        #endregion
                        break;
                    case "BOM_CHECK_STATUS":
                        #region Command "BOM_CHECK_STATUS"
                        {
                            if (alreadyinitialized)
                            {
                                if (bomCheckResult.AsyncWaitHandle.WaitOne(1, false))
                                {
                                    object res = bomCheckCaller.EndInvoke(bomCheckResult);
                                    result.Success = true;
                                    result.Result = res;
                                }
                                else
                                {
                                    result.Success = false;
                                    result.Result = null;
                                }
                            }
                        }
                        #endregion
                        break;
                    case "UPLOAD_AND_DISPATCH":
                        #region Command "UPLOAD_AND_DISPATCH"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string serialNumber = parameters[0].ToString();
                                string customerSN = parameters[1].ToString();
                                int failStation = Convert.ToInt32(parameters[2]);
                                bool isDispatch = Convert.ToBoolean(parameters[3]);
                                hardwaredriver.FileName = parameters[4].ToString();
                                uploadAndDispatchCaller = new UploadAndDispatch(this.hardwaredriver.UploadAndDispatch);
                                uploadAndDispatchResult = uploadAndDispatchCaller.BeginInvoke(serialNumber, customerSN, failStation, isDispatch, null, null);
                            }
                        }
                        #endregion
                        break;
                    case "UPLOAD_AND_DISPATCH_STATUS":
                        #region Command "UPLOAD_AND_DISPATCH_STATUS"
                        {
                            if (alreadyinitialized)
                            {
                                if (uploadAndDispatchResult.AsyncWaitHandle.WaitOne(1, false))
                                {
                                    object res = uploadAndDispatchCaller.EndInvoke(uploadAndDispatchResult);
                                    result.Success = true;
                                    result.Result = res;
                                }
                                else
                                {
                                    result.Success = false;
                                    result.Result = null;
                                }
                            }
                        }
                        #endregion
                        break;
                    case "CREATE_NEW_BOX":
                        #region Command "CREATE_NEW_BOX"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string materialBinNr;
                                double quantity;
                                double totalQuantity;
                                int ret = this.hardwaredriver.CreateNewBox(out materialBinNr, out quantity, out totalQuantity);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, materialBinNr, quantity, totalQuantity });
                            }
                        }
                        #endregion
                        break;
                    case "SET_EXISTING_BOX":
                        #region Command "CREATE_NEW_BOX"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                this.hardwaredriver.ExistingBoxNr = parameters[0].ToString();
                                result.Success = true;
                                result.Result = hardwaredriver.ExistingBoxNr;
                                string materialBinNr;
                                double quantity;
                                double totalQuantity;
                                int ret = this.hardwaredriver.ActivateExistingBox(parameters[0].ToString(), out materialBinNr, out quantity, out totalQuantity);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, materialBinNr, (int)quantity, (int)totalQuantity });
                            }
                        }
                        #endregion
                        break;
                    case "ACTIVATE_EXISTING_BOX":
                        #region Command "ACTIVATE_EXISTING_BOX"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string scannedBoxNr = parameters[0].ToString();
                                string materialBinNr;
                                double quantity;
                                double totalQuantity;
                                int ret = this.hardwaredriver.ActivateExistingBox(scannedBoxNr, out materialBinNr, out quantity, out totalQuantity);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, materialBinNr, (int)quantity, (int)totalQuantity });
                            }
                        }
                        #endregion
                        break;
                    case "ADD_SN_TO_BOX":
                        #region Command "ADD_SN_TO_BOX"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string scannedCustomerSNR = parameters[0].ToString();
                                string dispatchMaterialNr;
                                int quantity;
                                int ret = this.hardwaredriver.AddSnToBox(scannedCustomerSNR, out dispatchMaterialNr, out quantity);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret.ToString() , dispatchMaterialNr, quantity});
                            }
                        }
                        #endregion
                        break;
                    case "DISPATCH":
                        #region Command "DISPATCH"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                bool isFilled = Convert.ToBoolean( parameters[0] );
                                hardwaredriver.FileName = parameters[1].ToString();
                                int ret = this.hardwaredriver.Dispatch(isFilled);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret });
                            }
                        }
                        #endregion
                        break;
                    case "FUNCTION_TEST":
                        #region Command "FUNCTION_TEST"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string sn = parameters[0].ToString();
                                int ret = this.hardwaredriver.ActivateMaterialBox(sn);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = ret;
                            }
                        }
                        #endregion
                        break;
                    /*case "REPRINT":
                        #region Command "REPRINT"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                //todo change
                                hardwaredriver.FileName = parameters[3].ToString();
                                bool ret = this.hardwaredriver.PrintExcel(parameters[0].ToString(), 111, parameters[2].ToString());
                                if (!ret)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = ret;
                            }
                        }
                        #endregion
                        break;*/
                    #endregion
                    //housing
                    case "CHECK_CONNECTION":
                        #region Command "CHECK_CONNECTION"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string stationNr = parameters[0].ToString();
                                result.Success = this.hardwaredriver.CheckConnection(stationNr);
                            }
                        }
                        #endregion
                        break;
                    case "GETBOMITEMS":
                        #region Command "GETBOMITEMS"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string productNO = parameters[0].ToString();
                                DataTable dt;
                                int ret = this.hardwaredriver.GetBomItems(productNO, out dt);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, dt });
                            }
                        }
                        #endregion
                        break;
                    case "ACTIVEMATERIAL":
                        #region Command "ACTIVEMATERIAL"
                        {
                            if (alreadyinitialized)
                            {                               
                                _Current_Command = command;
                                string sn = parameters[0].ToString();
                                DataTable dt;
                                string errorstring;
                                int ret = this.hardwaredriver.CheckMaterial(sn, out dt, out errorstring);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, dt , errorstring});
                            }
                        }
                        #endregion
                        break;
                    case "UPLOADSTATE":
                        #region Command "UPLOADSTATE"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string sn = parameters[0].ToString();
                                int state = int.Parse(parameters[1].ToString());
                                int totalQuantity = int.Parse(parameters[2].ToString());
                                string printFileName = parameters[3].ToString();
                                bool dispatchFlag = bool.Parse(parameters[4].ToString());
                                string[] materialArray = (string [])parameters[5];//, parameters[6].ToString() };
                                bool[] enableArray = (bool[])parameters[6];
                                int quantity;
                                DataTable dt;
                                string errorstring;
                                int ret = this.hardwaredriver.UploadState(sn, state, totalQuantity, printFileName, dispatchFlag ,materialArray, enableArray, out quantity, out dt, out errorstring);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, quantity, dt , errorstring});
                            }
                        }
                        #endregion
                        break;
                    case "INSERTHOUSINGMATERIAL":
                        #region Command "INSERTHOUSINGMATERIAL"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string sn = parameters[0].ToString();
                                DataTable dt;
                                int ret = this.hardwaredriver.InsertHousingMaterial(sn , out dt);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret , dt});
                            }
                        }
                        #endregion
                        break;
                    case "PRINT_TEMP_NR":
                        #region Command "PRINT_TEMP_NR"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                int quantity = int.Parse(parameters[0].ToString());
                                string printFileName = parameters[1].ToString();
                                int ret = this.hardwaredriver.PrintTempNr(quantity, printFileName);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret });
                            }
                        }
                        #endregion
                        break;
                    case "REPRINT":
                        #region Command "REPRINT"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                int quantity = int.Parse(parameters[0].ToString());
                                string printFileName = parameters[1].ToString();
                                int ret = this.hardwaredriver.Reprint(quantity, printFileName);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret });
                            }
                        }
                        #endregion
                        break;
                    case "ASSEMBLY":
                        #region Command "ASSEMBLY"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                int quantity = int.Parse(parameters[0].ToString());
                                int ret = this.hardwaredriver.Assembly(quantity);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret });
                            }
                        }
                        #endregion
                        break;
                    case "LOADCANDLL":
                        #region Command "LOADCANDLL"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string dllName = parameters[0].ToString();
                                int ret = this.hardwaredriver.LoadCanDll(dllName);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret });
                            }
                        }
                        #endregion
                        break;
                    case "FREECANDLL":
                        #region Command "FREECANDLL"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                int ret = this.hardwaredriver.FreeCanDll();
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret });
                            }
                        }
                        #endregion
                        break;
                    case "GETECUSN":
                        #region Command "GETECUSN"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string sn, errMsg;
                                int size;
                                int ret = this.hardwaredriver.GetEcuSN(out sn, out size, out errMsg);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, sn, size, errMsg});
                            }
                        }
                        #endregion
                        break;
                    case "GETHOUSINGASSEMBLYSN":
                        #region Command "GETHOUSINGASSEMBLYSN"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;

                                if (!this.hardwaredriver.GetSerialnumberInfo(parameters[0].ToString()))
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = this.hardwaredriver.SerialNumberInfo.partNr;
                            }
                        }
                        #endregion
                        break;

                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
                alreadyinitialized = false;
                RaiseEvent("DISCONNECT", true, null);
                if (hardwaredriver != null)
                    hardwaredriver.Close();
            }
            return result;
        }
        
        private void hardwaredriver_OnConnected(object sender, int e)
        {
            RaiseEvent("CONNECTED", true, null);
        }

        private void hardwaredriver_OnConnectClosed(object sender, int e)
        {
            alreadyinitialized = false;

            RaiseEvent("DISCONNECTED", true, null);
        }

        #region Variable, common for each hardware, hardware related

        private AutoResetEvent _Signal_Command_Finished = new AutoResetEvent(false);
        private string[] _Received_Data = null;
        private String _Current_Command = String.Empty;
        private uint _Current_Tag = 0;
        private bool _TLVRequest_Result = false;
        #endregion

        public void RaiseEvent(string command, bool status, object result)
        {
            StationEventArgs arg = new StationEventArgs(hardwareName, command, status, result);
            eventClient.RaiseEvent(hardwareEvent, arg);
        }
    }
}
